﻿/*******************************************************************************
* 
*Author         :  VN
*Description    :  网络通信模块服务器协议包打包、加解密、解压缩
*Other          :  none
*Modify Record  :  none
*
*******************************************************************************/

using System.Collections.Generic;
using System.Collections;
using System.Text;
using System;
using System.IO;
using System.Net;
using System.Reflection;
using ProtoBuf;
using cs;
using UnityEngine;

namespace Network
{
    public class  CmdPack
    {
        public CmdPack() { }
        public CmdPack(uint cID, uint sNO, byte[] buffer)
        {
            Set(cID,sNO,buffer);
        }

        public void Set(uint cID, uint sNO, byte[] buffer)
        {
            cmdID = cID;
            seqNO = sNO;
            buf = buffer;
        }

        public uint cmdID = 0;
        public uint seqNO = 0;
        public byte[] buf = null;
    }

    public class PackCodec
    {
        CSPkgHead m_csPkgHead = new CSPkgHead(); //复用
        CSPKG m_pkg = new CSPKG();
        static MemoryStream m_stream = new MemoryStream();
        Encryption m_encryption = null;     //加解密
        bool m_bEncrypt = false;

        private uint m_srvTimeStamp;
        private uint m_srvSetTime;
        public  uint srvTimeStamp
        {
            get
            {
                System.TimeSpan ts = System.DateTime.Now - System.DateTime.Parse("1970-1-1");
                uint curTime = (uint)ts.TotalSeconds;
                uint time = m_srvTimeStamp + (curTime - m_srvSetTime);
                return time;
            }
            set
            {
                System.TimeSpan ts = System.DateTime.Now - System.DateTime.Parse("1970-1-1");
                m_srvSetTime = (uint)ts.TotalSeconds;
                m_srvTimeStamp = value;
            }
        }

        // 压缩相关
        const int COMPRESS_SIZE = 1024;   // 缺省
        private uint m_uCompressSize = 0;  // 超过这么多bit则需要压缩

        public PackCodec()
        {
        // m_encryption = new Encryption();
        }

        public void SetCompressSize(uint compressSize)
        {
            m_uCompressSize = compressSize;
        }

        public void SetSecretKey(byte[] key)
        {
            if (m_encryption == null)
            {
                m_encryption = new Encryption();
            }
            m_encryption.SetSecretKey(key);
        }

        public void EnabledEncrypt(bool b) 
        {
            m_bEncrypt = b;
        }

        public ByteBuffer PackData(CmdPack cmdPack)
        {
            CSPKG pkg = GetPKG();
            pkg.Head = PackHeader(cmdPack.cmdID, cmdPack.seqNO);
            pkg.Body = cmdPack.buf;

            if (m_uCompressSize == 0)
            {
                m_uCompressSize = COMPRESS_SIZE;
            }
            if (pkg.Body.Length > m_uCompressSize)
            {
//                 int origSize = pkg.Body.Length;
//                 pkg.Head.CompressType = (uint)cs.EnmCompressType.ENM_COMPRESS_TYPE_GZIP;
// 
//                 pkg.Body = Encoding.UTF8.GetBytes("Hello World");
//                 pkg.Body = Util.CompressBytes(pkg.Body); //ZlibStream.CompressBuffer(pkg.Body);
            //    int curSize = pkg.Body.Length;
            }

            // 需要加密就
            if (m_encryption != null && pkg.Body.Length > 0 && m_bEncrypt)
            {
                pkg.Head.EncryptType = (uint)cs.EnmEncryptType.ENM_ENCRYPT_TYPE_XXTEA;
                pkg.Body = m_encryption.Encrypt(pkg.Body);
            }

            byte[] sendbuf = Serialize<CSPKG>(pkg);
            ByteBuffer byteBuf = new ByteBuffer();
            byteBuf.WriteNetBytes(sendbuf);

            return byteBuf;
        }

        public CSPKG UnPackData(byte[] pData)
        {
            CSPKG pkg = (CSPKG)Deserialize<CSPKG>(pData);
            if (pkg == null)
            {
                return null;
            }

            // 设置时间戳
//            srvTimeStamp = pkg.Head.Timestamp;

            // 解密
            if (pkg.Head.EncryptType == (uint)cs.EnmEncryptType.ENM_ENCRYPT_TYPE_XXTEA)
            {
                pkg.Body = m_encryption.Decrypt(pkg.Body);
                if (pkg.Body == null)
                {
                    return null;
                }
            }

            // 解压缩
//             if (pkg.Head.CompressType == (uint)cs.EnmCompressType.ENM_COMPRESS_TYPE_GZIP)
//             {
//                 int oSize = pkg.Body.Length;
//                 pkg.Body = Util.DecompressBytes(pkg.Body);
//                 int curSize = pkg.Body.Length;
//             }
            return pkg;
        }

        static public byte[]  Serialize<T>(T msg)
        {
            byte[] result = null;
            if (msg != null)
            {
                using (var stream = new MemoryStream())
                {
                    Serializer.Serialize<T>(stream, msg);
                    result = stream.ToArray();
                }
            }
            return result;
        }

        static public T Deserialize<T>(byte[] message)
        {
            T result = default(T);
            if (message != null) 
            {
                using (var stream = new MemoryStream(message))
                {
                    result = Serializer.Deserialize<T>(stream);
                }
            }

            return result;
        }

        private CSPkgHead PackHeader(uint cmdID, uint nSeqId)
        {
            m_csPkgHead.CmdID = cmdID;
            m_csPkgHead.MsgSeqID = nSeqId;
            m_csPkgHead.EncryptType = (uint)cs.EnmEncryptType.ENM_ENCRYPT_TYPE_NONE;
            m_csPkgHead.CompressType = (uint)cs.EnmCompressType.ENM_COMPRESS_TYPE_NONE;
            return m_csPkgHead;
        }

        CSPKG GetPKG()
        {
            return m_pkg;
        }
    }
}